﻿using System;
using System.Threading.Tasks;
using System.Security;
using HiCore.Extensions.UnitOfWork.EntityFramework;
using HiCore.WebApi.Example.DbContexts;
using HiCore.WebApi.Example.DbContexts.DbEntity;
using HiCore.WebApi.Example.IRepository;
using HiCore.WebApi.Example.DomainEvents;

namespace HiCore.WebApi.Example.Repository
{
    internal class TestRepository : Repository<TestTable>, IRepository<TestTable>, ITestRepository
    {
        private readonly IUnitOfWork<MyDbContext> _unitOfWork;
        private readonly IRepository<TestTable> _repository;
        public TestRepository(IUnitOfWork<MyDbContext> unitOfWork) : base(unitOfWork.DbContext)
        {
            _unitOfWork = unitOfWork;
            _repository = _unitOfWork.GetRepository<TestTable>();
        }

        public Task<int> AddAsync()
        {
            var addEntity = new TestTable
            {
                Id = new Random().Next(100, int.MaxValue),
                CreateTime = DateTime.Now,
                Mobile = Guid.NewGuid().ToString(),
                //Password = BuildPassword()
            };
            addEntity.AddDomainEvent(new AccountCreatedEvent() { UserId = addEntity.Id, LoginName = addEntity.Mobile });
            _ = _repository.AddAsync(addEntity);
            return _unitOfWork.SaveChangesAsync();
        }

        public async Task<int> UpdateAsync(int id)
        {
            var entity = await _repository.FirstOrDefaultAsync(w => w.Id == id);

            entity.Mobile = "dddddddddddddddd";
            _repository.Update(entity);

            return await _unitOfWork.SaveChangesAsync();
        }

        public Task<int> RemoveAsync(int id)
        {
            return _repository.RemoveAsync(x => x.Id == id);
        }

        public Task<TestTable> GetAsync(int id)
        {
            return _repository.FirstOrDefaultAsync(w => w.Id == id);
        }

        public Task<int> ExecuteAsync(int id)
        {
            return _repository.ExecuteAsync("update aaaaaa_test set createtime=@createtime where id=@id", new { id = id, createtime = DateTime.Now });
        }

        /// <summary>
        /// 带条件修改无法加密(执行原生SQL)
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<int> UpdateRangeAsync(int id)
        {
            //string s = LambdaToSqlHelper.GetSqlFromExpression<TestTable>(x => x.Mobile == x.Mobile + "_" + id + "_newKey");
            return _repository.UpdateAsync(x => x.Id == id, x => x.Mobile == id + "_newKey");
        }

        public Task Transaction(int id)
        {
            _unitOfWork.Transaction(() =>
            {
                //修改的对象必须为同一引用，否则多次跟踪报错
                var updated = new TestTable { Id = id, Mobile = "11111" };

                updated.Mobile = "11111";
                _repository.Update(updated, w => w.Mobile);
                int a = _unitOfWork.SaveChanges();

                updated.Mobile = "ddddddddddddddddddd";
                _repository.Update(updated, w => w.Mobile);
                int b = _unitOfWork.SaveChanges();

                updated.Mobile = "ccccccccccccccccccccc";
                _repository.Update(updated, "Mobile");
                int c = _unitOfWork.SaveChanges();


                //_repository.Add(new TestTable
                //{
                //    Id = new Random().Next(100, int.MaxValue),
                //    CreateTime = DateTime.MinValue,// DateTime.Now,
                //    Mobile = Guid.NewGuid().ToString(),
                //    Password = "11111111111111111111111111", //BuildPassword()
                //});

                //int c = _unitOfWork.SaveChanges();

            });
            return Task.CompletedTask;
        }

        private SecureString BuildPassword()
        {
            SecureString result = new();
            result.AppendChar('L');
            result.AppendChar('e');
            result.AppendChar('t');
            result.AppendChar('M');
            result.AppendChar('e');
            result.AppendChar('I');
            result.AppendChar('n');
            result.AppendChar('!');
            result.MakeReadOnly();
            return result;
        }
    }
}
